﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Data;
using System.Data.SqlClient;
using libUtilities;

namespace ThresholdModeling
{
    public class TMUtils
    {
        //public static bool SaveGroup(List<MemberInfo> mems)
        //{
        //    try
        //    {
        //        MembersGroup group = mems[0].Group;
        //        String dir = OtherUtils.getPath() + @"\Data\Group";
        //        String fileName = "Group" + group.GroupID + " - " + group.GroupName + ".xml";
        //        File.Delete(dir + @"\" + fileName);
        //        XmlDocument doc = OtherUtils.initXml(dir, fileName, true);
        //        XmlNode root = doc.DocumentElement;

        //        //Group info
        //        XmlNode groupInfo = doc.CreateNode(XmlNodeType.Element, "GroupInfo", null);

        //        XmlNode id = doc.CreateNode(XmlNodeType.Element, "id", null);
        //        id.InnerText = group.GroupID.ToString();
        //        groupInfo.AppendChild(id);

        //        XmlNode name = doc.CreateNode(XmlNodeType.Element, "name", null);
        //        name.InnerText = group.GroupName;
        //        groupInfo.AppendChild(name);

        //        XmlNode pass = doc.CreateNode(XmlNodeType.Element, "password", null);
        //        pass.InnerText = group.Password;
        //        groupInfo.AppendChild(pass);

        //        XmlNode n = doc.CreateNode(XmlNodeType.Element, "n", null);
        //        n.InnerText = group.NMembers.ToString();
        //        groupInfo.AppendChild(n);

        //        XmlNode k = doc.CreateNode(XmlNodeType.Element, "k", null);
        //        k.InnerText = group.KMembers.ToString();
        //        groupInfo.AppendChild(k);

        //        XmlNode M = doc.CreateNode(XmlNodeType.Element, "M", null);
        //        M.InnerText = group.M.ToString();
        //        groupInfo.AppendChild(M);

        //        XmlNode hashSecret = doc.CreateNode(XmlNodeType.Element, "secret", null);
        //        hashSecret.InnerText = group.HashSecret.ToString();
        //        groupInfo.AppendChild(hashSecret);

        //        root.AppendChild(groupInfo);

        //        //Members
        //        XmlNode groupMembers = doc.CreateNode(XmlNodeType.Element, "GroupMembers", null);
        //        foreach (MemberInfo mem in mems)
        //        {
        //            XmlNode memberNode = doc.CreateNode(XmlNodeType.Element, "Members", null);

        //            XmlNode memID = doc.CreateNode(XmlNodeType.Element, "id", null);
        //            memID.InnerText = mem.MemberID;
        //            memberNode.AppendChild(memID);

        //            XmlNode memName = doc.CreateNode(XmlNodeType.Element, "name", null);
        //            memName.InnerText = mem.Name;
        //            memberNode.AppendChild(memName);

        //            XmlNode memEmail = doc.CreateNode(XmlNodeType.Element, "email", null);
        //            memEmail.InnerText = mem.Email;
        //            memberNode.AppendChild(memEmail);

        //            XmlNode memRole = doc.CreateNode(XmlNodeType.Element, "role", null);
        //            memRole.InnerText = mem.Role;
        //            memberNode.AppendChild(memRole);

        //            XmlNode memI = doc.CreateNode(XmlNodeType.Element, "I", null);
        //            memI.InnerText = mem.I.ToString();
        //            memberNode.AppendChild(memI);

        //            XmlNode memmi = doc.CreateNode(XmlNodeType.Element, "mi", null);
        //            memmi.InnerText = mem.mi.ToString();
        //            memberNode.AppendChild(memmi);

        //            groupMembers.AppendChild(memberNode);
        //        }

        //        root.AppendChild(groupMembers);

        //        doc.Save(dir + @"\" + fileName);
        //        return true;
        //    }
        //    catch 
        //    {
        //        return false;
        //    }
        //}

        //public static List<MemberInfo> LoadGroup(int idx)
        //{
        //    List<MemberInfo> members = new List<MemberInfo>();
        //    try
        //    {
        //        String dir = OtherUtils.getPath() + @"\Data\Group";
        //        String file = GetFilesInDirectory(dir)[idx] + ".xml";
        //        XmlDocument doc = OtherUtils.initXml(dir, file);
        //        XmlNode root = doc.DocumentElement;

        //        XmlNode groupNode = root["GroupInfo"];

        //        int groupID = int.Parse(groupNode["id"].InnerText);
        //        String groupName = groupNode["name"].InnerText;
        //        String pass = groupNode["password"].InnerText;
        //        int n = int.Parse(groupNode["n"].InnerText);
        //        int k = int.Parse(groupNode["k"].InnerText);
        //        BigInteger M = BigInteger.Parse(groupNode["M"].InnerText);
        //        String hs = groupNode["secret"].InnerText;
        //        MembersGroup group = new MembersGroup(groupID, groupName, pass, n, k, M, hs);

        //        XmlNode membersNode = root["GroupMembers"];
        //        XmlNodeList nodes = membersNode.ChildNodes;
        //        foreach (XmlNode node in nodes)
        //        {
        //            String id = node["id"].InnerText;
        //            String name = node["name"].InnerText;
        //            String email = node["email"].InnerText;
        //            String role = node["role"].InnerText;

        //            members.Add(new MemberInfo(id, name, email, role, group));
        //        }

        //        return members;
        //    }
        //    catch (XmlException ex)
        //    {
        //        return null;
        //    }
        //}

        //public static MembersGroup LoadGroupInfo(int idx)
        //{
        //    MembersGroup group = null;
        //    try
        //    {
        //        String dir = OtherUtils.getPath() + @"\Data\Group";
        //        String file = GetFilesInDirectory(dir)[idx] + ".xml";
        //        XmlDocument doc = OtherUtils.initXml(dir, file);
        //        XmlNode root = doc.DocumentElement;

        //        XmlNode groupNode = root["GroupInfo"];

        //        int MemberID = int.Parse(groupNode["id"].InnerText);
        //        String MemberName = groupNode["name"].InnerText;
        //        String pass = groupNode["password"].InnerText;
        //        int n = int.Parse(groupNode["n"].InnerText);
        //        int k = int.Parse(groupNode["k"].InnerText);
        //        BigInteger M = BigInteger.Parse(groupNode["M"].InnerText);
        //        String hs = groupNode["secret"].InnerText;
        //        group = new MembersGroup(MemberID, MemberName, pass, n, k, M, hs);

        //        return group;
        //    }
        //    catch (XmlException ex)
        //    {
        //        return null;
        //    }
        //}

        //public static string[] GetFilesPathInDirectory(String dir)
        //{
        //    try
        //    {
        //        bool exist = Directory.Exists(dir);
        //        if (!exist)
        //        {
        //            return null;
        //        }
        //        return Directory.GetFiles(dir);

        //    }
        //    catch (XmlException ex)
        //    {
        //        throw ex;
        //    }
        //}

        //public static string[] GetFilesInDirectory(String dir)
        //{
        //    try
        //    {
        //        bool exist = Directory.Exists(dir);
        //        if (!exist)
        //        {
        //            return null;
        //        }
        //        string[] files = Directory.GetFiles(dir);
        //        string[] filesName = new string[files.Length];
        //        int i = 0;
        //        foreach (string file in files)
        //        {
        //            filesName[i] = GetFileNameFromPath(files[i]);
        //            i++;
        //        }
        //        return filesName;
        //    }
        //    catch (XmlException ex)
        //    {
        //        throw ex;
        //    }
        //}

        //private static String GetFileNameFromPath(String path)
        //{
        //    int i;
        //    for (i = path.Length - 1; i >= 0; i--)
        //    {
        //        if (path[i]=='\\')
        //            break;
        //    }
        //    return path.Substring(i + 1, path.Length - 1 - i - 4);//not get file extension
        //}

        public static bool SendMail(List<MemberInfo> members, String address, String password)
        {
            try
            {
                ////Find Admin mail
                //MemberInfo admin = null;
                //foreach (MemberInfo mem in members)
                //{
                //    if (mem.isAdmin())
                //    {
                //        admin = new MemberInfo(mem);
                //        break;
                //    }
                //}
                //if (admin == null)
                //    return false;

                var fromAddress = new MailAddress(address, "Admin of N members System");
                //var toAddress = new MailAddress("pf2707@yahoo.com.vn", "To Name");
                string fromPassword = password;
                String subject = "";
                String body = "";

                var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    Credentials = new NetworkCredential(fromAddress.Address, fromPassword),
                    Timeout = 20000
                };
                MembersGroup group = members[0].Group;
                foreach (MemberInfo mem in members)
                {
                    var toAddress = new MailAddress(mem.Email, mem.Name);
                    subject = mem.Group.GroupName + " - " + "Shared Secret Information";
                    body = "Member login information: \n";
                    body += "I = " + mem.I.ToString() + "\n" + "m = " + mem.mi.ToString() + "\n";
                    body += "\n\n";
                    body += "Use for Cryptography\n";
                    body += "key = " + group.K_ExpMod + "\n";
                    body += "prime = " + group.P_ExpMod + "\n";

                    using (var message = new MailMessage(fromAddress, toAddress)
                    {
                        Subject = subject,
                        Body = body
                    })
                    {
                        smtp.Send(message);
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static void WriteFile(String path, String src)
        {
            try
            {
                StreamWriter sw = new StreamWriter(path);
                sw.Write(src);
                sw.Close();
            }
            catch (IOException ex)
            {
                throw ex;
            }
        }

        #region SQL Database
        private static String connectionString;
        private static SqlConnection connection = null;
        private static SqlConnection ConnectDatabase()
        {
            try
            {
                connectionString = ReadConnectionString(Directory.GetCurrentDirectory() + @"\Data\Dataset\ConnectionString\ConnectionString.xml");
                SqlConnection con = new SqlConnection(connectionString);
                con.Open();
                con.Close();
                return con;
            }
            catch(Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                return null;
            }
        }

        private static String ReadConnectionString(String file)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(file);
                XmlElement root = doc.DocumentElement;
                String connectionString = root.InnerText;
                return connectionString;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        public static bool InitDatabase()
        {
            try
            {
                connection = ConnectDatabase();
                if (connection != null)
                    return true;
                return false;
            }
            catch (SqlException se)
            {
                //throw se;
                return false;
            }
        }

        public static List<MembersGroup> LoadGroupsName()
        {
            try
            {
                List<MembersGroup> groups = new List<MembersGroup>();
                List<SqlParameter> sqlParams = new List<SqlParameter>();
                DataTable dtGroups = ExecuteQuery("sp_selectAllGroupsName", null);

                foreach (DataRow dt in dtGroups.Rows)
                {
                    int id = int.Parse(dt["GroupID"].ToString());
                    String gName = dt["GroupName"].ToString();
                    groups.Add(new MembersGroup(id, gName));
                }
                return groups;
            }
            catch
            {
                return null;
            }
        }

        public static List<MemberInfo> LoadGroup(int id)
        {
            try
            {
                List<MemberInfo> members = new List<MemberInfo>();

                List<SqlParameter> sqlParams = new List<SqlParameter>();
                sqlParams.Add(new SqlParameter("@id", id));
                DataTable dtGroup = ExecuteQuery("sp_selectGroup", sqlParams);
                if (dtGroup.Rows.Count != 1)
                    return null;

                String gName = dtGroup.Rows[0]["GroupName"].ToString();
                String gPass = dtGroup.Rows[0]["Password"].ToString();
                int N = int.Parse(dtGroup.Rows[0]["N"].ToString());
                int k = int.Parse(dtGroup.Rows[0]["k"].ToString());
                BigInteger M = BigInteger.Parse(dtGroup.Rows[0]["M"].ToString());
                String hs = dtGroup.Rows[0]["HashSecret"].ToString();
                int kExp = int.Parse(dtGroup.Rows[0]["k_Exponent"].ToString());
                int pExp = int.Parse(dtGroup.Rows[0]["p_Exponent"].ToString());
                MembersGroup group = new MembersGroup(id, gName, gPass, N, k, M, hs, kExp, pExp);

                //Load members
                sqlParams.Clear();
                sqlParams.Add(new SqlParameter("@groupID", id));
                DataTable dtMembers = ExecuteQuery("sp_selectMemberByGroup", sqlParams);
                foreach (DataRow dt in dtMembers.Rows)
                {
                    String memID = dt["MemberID"].ToString();
                    String memName = dt["MemberName"].ToString();
                    String memRole = dt["MemberRole"].ToString();
                    String memEmail = dt["MemberEmail"].ToString();

                    members.Add(new MemberInfo(memID, memName, memEmail, memRole, group));
                }

                return members;

            }
            catch (SqlException se)
            {
                return null;
            }
        }

        public static MembersGroup LoadGroupInfo(int id)
        {
            try
            {
                List<SqlParameter> sqlParams = new List<SqlParameter>();
                sqlParams.Add(new SqlParameter("@id", id));
                DataTable dtGroup = ExecuteQuery("sp_selectGroup", sqlParams);
                if (dtGroup.Rows.Count != 1)
                    return null;

                String gName = dtGroup.Rows[0]["GroupName"].ToString();
                String gPass = dtGroup.Rows[0]["Password"].ToString();
                int N = int.Parse(dtGroup.Rows[0]["N"].ToString());
                int k = int.Parse(dtGroup.Rows[0]["k"].ToString());
                BigInteger M = BigInteger.Parse(dtGroup.Rows[0]["M"].ToString());
                String hs = dtGroup.Rows[0]["HashSecret"].ToString();
                int kExp = int.Parse(dtGroup.Rows[0]["k_Exponent"].ToString());
                int pExp = int.Parse(dtGroup.Rows[0]["p_Exponent"].ToString());
                MembersGroup group = new MembersGroup(id, gName, gPass, N, k, M, hs, kExp, pExp);

                return group;
            }
            catch
            {
                return null;
            }
        }

        public static bool SaveGroup(List<MemberInfo> mems, String editType)
        {
            try
            {
                int n = 0;
                bool iuGroupInfo = false;
                bool iuMemberInfo = true;

                List<MembersGroup> gs = LoadGroupsName();
                int newGroupID = -1;
                if (gs.Count == 0)
                    newGroupID = 0;
                else
                    newGroupID = gs[gs.Count - 1].GroupID + 1;

                MembersGroup group = mems[0].Group;
                List<SqlParameter> sqlParams = new List<SqlParameter>();
                sqlParams.Add(new SqlParameter("@name", group.GroupName));
                sqlParams.Add(new SqlParameter("@password", group.Password));
                sqlParams.Add(new SqlParameter("@N", group.NMembers));
                sqlParams.Add(new SqlParameter("@k", group.KMembers));
                sqlParams.Add(new SqlParameter("@M", group.M.ToString()));
                sqlParams.Add(new SqlParameter("@hs", group.HashSecret));
                sqlParams.Add(new SqlParameter("@kExp", group.K_ExpMod));
                sqlParams.Add(new SqlParameter("@pExp", group.P_ExpMod));
                
                if ("insert".Equals(editType))
                {
                    sqlParams.Add(new SqlParameter("@id", newGroupID));
                    n = ExecuteNoneQuery("sp_insertNewGroup", sqlParams);
                }
                else if ("update".Equals(editType))
                {
                    sqlParams.Add(new SqlParameter("@id", group.GroupID));
                    n = ExecuteNoneQuery("sp_updateGroup", sqlParams);

                    sqlParams.Clear();
                    sqlParams.Add(new SqlParameter("@id", group.GroupID));
                    ExecuteNoneQuery("sp_deleteMemberByGroup", sqlParams);
                }
                if (n == 1)
                    iuGroupInfo = true;

                sqlParams.Clear();

                if (iuGroupInfo)
                {
                    int groupID = "insert".Equals(editType) ? newGroupID : group.GroupID;
                    foreach (MemberInfo member in mems)
                    {
                        //insert members info
                        sqlParams.Add(new SqlParameter("@id", member.MemberID));
                        sqlParams.Add(new SqlParameter("@name", member.Name));
                        sqlParams.Add(new SqlParameter("@role", member.Role));
                        sqlParams.Add(new SqlParameter("@email", member.Email));
                        sqlParams.Add(new SqlParameter("@groupID", groupID));

                        n = ExecuteNoneQuery("sp_insertNewMember", sqlParams);
                        //if ("insert".Equals(editType))
                        //{
                        //    n = ExecuteNoneQuery("sp_insertNewMember", sqlParams);
                        //}
                        //else if ("update".Equals(editType))
                        //{
                        //    n = ExecuteNoneQuery("sp_updateMember", sqlParams);
                        //}
                        if (n == 0)
                        {
                            iuMemberInfo = false;
                            break;
                        }
                        sqlParams.Clear();
                    }
                }

                if (iuGroupInfo && iuMemberInfo)
                    return true;
                return false;
            }
            catch (SqlException se)
            {
                System.Console.WriteLine(se.Message);
                throw se;
            }
        }

        public static bool DeleteGroup(int id)
        {
            try
            {
                int n = 0;
                List<SqlParameter> listParams = new List<SqlParameter>();
                listParams.Add(new SqlParameter("@id", id));
                n = ExecuteNoneQuery("sp_deleteMemberByGroup", listParams);
                if (n != 0)
                {
                    listParams.Clear();
                    listParams.Add(new SqlParameter("@id", id));
                    n = ExecuteNoneQuery("sp_deleteGroupByID", listParams);
                    if (n != 0)
                        return true;
                }
                return false;
            }
            catch (SqlException se)
            {
                throw se;
            }
        }

        public static DataTable ExecuteQuery(String spName, List<SqlParameter> sqlParams)
        {
            DataTable dt = new DataTable();
            try
            {
                SqlConnection connect = new SqlConnection(connectionString);
                connect.Open();
                try
                {
                    SqlCommand command = connect.CreateCommand();
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = spName;
                    if (sqlParams != null)
                    {
                        foreach (SqlParameter param in sqlParams)
                        {
                            command.Parameters.Add(param);
                        }
                    }
                    SqlDataAdapter adapter = new SqlDataAdapter();
                    adapter.SelectCommand = command;
                    adapter.Fill(dt);
                }

                catch (SqlException ex)
                {
                    throw ex;
                }
                finally
                {
                    connect.Close();
                }
            }

            catch (Exception ex)
            {
                throw ex;
            }
            return dt;
        }

        public static int ExecuteNoneQuery(String spName, List<SqlParameter> sqlParams)
        {
            int n;
            try
            {
                SqlConnection connect = new SqlConnection(connectionString);
                connect.Open();
                try
                {
                    SqlCommand command = connect.CreateCommand();
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = spName;
                    if (sqlParams != null)
                    {
                        foreach (SqlParameter param in sqlParams)
                        {
                            command.Parameters.Add(param);
                        }
                    }
                    n = command.ExecuteNonQuery();
                }

                catch (SqlException ex)
                {
                    throw ex;
                }
                finally
                {
                    connect.Close();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return n;
        }
        #endregion
    }
}
